from __future__ import absolute_import
import ctypes
import os
import sys

def find_lib_path(name=None, search_path=None, optional=False):
    """Find dynamic library files.

    Parameters
    ----------
    name : list of str
        List of names to be found.

    Returns
    -------
    lib_path : list(string)
        List of all found path to the libraries
    """
    ffi_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__)))
    source_dir = os.path.join(ffi_dir, "..", "..")

    dll_path = []

    if os.environ.get('NNE_LIBRARY_PATH', None):
        dll_path.append(os.environ['NNE_LIBRARY_PATH'])

    if sys.platform.startswith('linux') and os.environ.get('LD_LIBRARY_PATH', None):
        dll_path.extend([p.strip() for p in os.environ['LD_LIBRARY_PATH'].split(":")])
    elif sys.platform.startswith('darwin') and os.environ.get('DYLD_LIBRARY_PATH', None):
        dll_path.extend([p.strip() for p in os.environ['DYLD_LIBRARY_PATH'].split(":")])

    # Default cmake build directory
    dll_path.append(os.path.join(source_dir, "build"))
    dll_path.append(os.path.join(source_dir, "build", "Release"))
    # Default make build directory
    dll_path.append(os.path.join(source_dir, "lib"))
    dll_path.append(source_dir)

    dll_path = [os.path.realpath(x) for x in dll_path]
    if search_path is not None:
        if search_path is list:
            dll_path = dll_path + search_path
        else:
            dll_path.append(search_path)
    if name is not None:
        if isinstance(name, list):
            lib_dll_path = []
            for n in name:
                lib_dll_path += [os.path.join(p, n) for p in dll_path]
        else:
            lib_dll_path = [os.path.join(p, name) for p in dll_path]
    else:
        if sys.platform.startswith('win32'):
            lib_dll_path = [os.path.join(p, 'libnne50v2.dll') for p in dll_path] +\
                           [os.path.join(p, 'nne50v2.dll') for p in dll_path] +\
                           [os.path.join(p, 'libnne_emulator.dll') for p in dll_path] +\
                           [os.path.join(p, 'nne_emulator.dll') for p in dll_path]
        elif sys.platform.startswith('darwin'):
            lib_dll_path = [os.path.join(p, 'libnne50v2.dylib') for p in dll_path] +\
                           [os.path.join(p, 'libnne50v2.so') for p in dll_path] +\
                           [os.path.join(p, 'libnne_emulator.dylib') for p in dll_path] +\
                           [os.path.join(p, 'libnne_emulator.so') for p in dll_path]
        else:
            lib_dll_path = [os.path.join(p, 'libnne50v2.so') for p in dll_path] +\
                           [os.path.join(p, 'libnne_emulator.so') for p in dll_path]
    # try to find lib_dll_path
    lib_found = [p for p in lib_dll_path if os.path.exists(p) and os.path.isfile(p)]

    if not lib_found:
        message = ('Cannot find the files.\n' +
                   'List of candidates:\n' +
                   str('\n'.join(lib_dll_path)))
        if not optional:
            raise RuntimeError(message)
        return None

    return lib_found

#----------------------------
# library loading
#----------------------------
#if sys.version_info[0] == 3:
#    string_types = (str,)
#    integer_types = (int, np.int32)
#    numeric_types = integer_types + (float, np.float32)
#    # this function is needed for python3
#    # to convert ctypes.char_p .value back to python str
#    if sys.platform == "win32":
#        encoding = 'cp' + str(ctypes.cdll.kernel32.GetACP())
#        py_str = lambda x: x.decode(encoding)
#    else:
#        py_str = lambda x: x.decode('utf-8')
#else:
#    string_types = (basestring,)
#    integer_types = (int, long, np.int32)
#    numeric_types = integer_types + (float, np.float32)
#    py_str = lambda x: x


def _load_lib():
    """Load libary by searching possible path."""
    lib_path = find_lib_path()
    print("use lib:",lib_path[0],"\n");
    lib = ctypes.CDLL(lib_path[0], ctypes.RTLD_GLOBAL)
    # DMatrix functions
    # lib.TVMGetLastError.restype = ctypes.c_char_p
    return lib, os.path.basename(lib_path[0])

_LIB, _LIB_PATH = _load_lib()
